package com.shuangfeidasan.service.ums.impl;

import com.shuangfeidasan.dto.AdminInfoParam;
import com.shuangfeidasan.dto.AdminLoginParam;
import com.shuangfeidasan.mapper.ums.*;
import com.shuangfeidasan.model.ums.*;
import com.shuangfeidasan.security.utils.JwtTokenUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description 用户安全服务类
 * @Author JunWEI
 * @Date 2022/1/22
 */
@Service
public class AdminSecurityService implements UserDetailsService {
    @Autowired
    UmsAdminMapper umsAdminMapper;
    @Autowired
    UmsAdminRoleRelationMapper umsAdminRoleRelationMapper;
    @Autowired
    UmsRoleMapper umsRoleMapper;
    @Autowired
    private PasswordEncoder passwordEncoder;
    @Autowired
    private JwtTokenUtil jwtTokenUtil;
    @Autowired
    private AdminSecurityDao adminSecurityDao;
    @Autowired
    private UmsMenuMapper umsMenuMapper;

    public UmsAdmin register(UmsAdmin umsAdmin) {
        umsAdmin.setCreateTime(new Date());
        umsAdmin.setStatus(1);
        //TODO: 查询是否有相同用户名的用户

        // 将密码进行加密操作
        String encodePassword = passwordEncoder.encode(umsAdmin.getPassword());
        umsAdmin.setPassword(encodePassword);

        if (umsAdminMapper.insert(umsAdmin) == 1) {
            return umsAdmin;
        }
        return null;
    }

    public String login(AdminLoginParam adminLoginParam) {
        String token = null;
        UserDetails userDetails = loadUserByUsername(adminLoginParam.getUsername());
        // TODO: 密码需要客户端加密后传递
        if (passwordEncoder.matches(adminLoginParam.getPassword(), userDetails.getPassword())) {
            UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authentication);
            token = jwtTokenUtil.generateToken(userDetails);
        }
        return token;
    }

    public UmsAdmin update(UmsAdmin umsAdmin) {
        umsAdmin.setPassword(passwordEncoder.encode(umsAdmin.getPassword()));
        if (umsAdminMapper.update(umsAdmin) == 1) {
            return umsAdmin;
        }
        return null;
    }

    @Override
    public UserDetails loadUserByUsername(String username) {
        //获取用户实体类
        UmsAdmin umsAdmin = this.getUmsAdminByUsername(username);
        if (umsAdmin != null) {
            List<UmsRole> roleList = this.getRoleList(umsAdmin);
            return new AdminUserDetails(umsAdmin, roleList);
        }
        throw new UsernameNotFoundException("用户名或密码错误");
    }

    private UmsAdmin getUmsAdminByUsername(String username) {
        UmsAdmin umsAdmin = new UmsAdmin();
        umsAdmin.setUsername(username);
        // TODO 判断是否只有一个结果
        umsAdmin = this.umsAdminMapper.queryAll(umsAdmin).get(0);
        return umsAdmin;
    }

    private List<UmsRole> getRoleList(UmsAdmin umsAdmin) {
        UmsAdminRoleRelation adminRoleRelation = new UmsAdminRoleRelation();
        adminRoleRelation.setAdminId(umsAdmin.getId());
        List<UmsAdminRoleRelation> adminRoleRelationList = umsAdminRoleRelationMapper.queryAll(adminRoleRelation);

        return adminRoleRelationList.stream()
                .map(item -> umsRoleMapper.queryById(item.getRoleId()))
                .collect(Collectors.toList());
    }

    public AdminInfoParam getUserInfo(String username) {
        //获取用户实体类
        UmsAdmin umsAdmin = this.getUmsAdminByUsername(username);
        if (umsAdmin == null) {
            throw new UsernameNotFoundException("用户名不存在，请重新登录");
        }
        List<UmsMenu> menuItemList = getMenuList(umsAdmin.getId());
        return AdminInfoParam.builder()
                .admin(umsAdmin)
                .menuList(menuItemList)
                .build();
    }

    public List<UmsMenu> getMenuList(Long adminId) {

        List<UmsMenu> menuItemList = adminSecurityDao.getMenuItemList(adminId);

        Map<Long, UmsMenu> topMenuMap = menuItemList.stream()
                .map(item -> umsMenuMapper.queryById(item.getParentId()))
                .collect(Collectors.toMap(UmsMenu::getId, Function.identity(), (existing, replacement) -> existing));

        for (UmsMenu menu : menuItemList) {
            UmsMenu parentMenu = topMenuMap.get(menu.getParentId());
            if (parentMenu != null) {
                parentMenu.getSubmenus().add(menu);
            }
        }

        return sortMenu(new ArrayList<>(topMenuMap.values()));
    }

    public List<UmsMenu> sortMenu(List<UmsMenu> menus) {
        menus.sort((a, b) -> (int) (a.getSort() - b.getSort()));
        menus.forEach(item -> item.getSubmenus().sort((a, b) -> (int) (a.getSort() - b.getSort())));
        return menus;
    }

}
